#include "road_part.h"
#include <iostream>
using namespace std;
using namespace adevs;

// Assign locally unique identifiers to the ports
const int RoadPart::in_arrive = 0;
const int RoadPart::in_free = 1;
const int RoadPart::out_depart = 2;
const int RoadPart::out_free = 3;

RoadPart::RoadPart(double dl):
	Atomic<IO_Type>(), // Initialize the parent Atomic model
	delay(dl),
	can_go(true),
	arived(false),
	vehicle(NULL),
	denied(0)
{
}

void RoadPart::delta_ext(double e, const Bag<IO_Type>& xb)
{
	Bag<IO_Type>::const_iterator i = xb.begin();
	for (; i != xb.end(); i++)
	{
		if ((*i).port == in_arrive)
		{ // prijizdi auto
			if (vehicle == NULL)
			{
				vehicle = new Vehicle(*((Vehicle*)(*i).value));
				arived = true;
				//cout << "RP("<<id<<": Prijelo auto!" << endl;
			}
			else
			{
				denied ++;
				//cout << "RP: auto nebylo schopno zaradit se!" << endl;
			}
		}
		else if ((*i).port == in_free)
		{ // je volno
			can_go = true;
		}
	}
}
	
void RoadPart::delta_int()
{
	if (vehicle != NULL)
	{
		if (arived)
		{
			arived = false;
			return;
		}
		if (can_go) // odjizdi vozidlo
		{
			vehicle = NULL; // odjelo
			can_go = false; // a dalsi nemuze

			//cout << "RP("<<id<<": auto odjelo!" << endl;
		}
	}
}

void RoadPart::delta_conf(const Bag<IO_Type>& xb)
{
	delta_int();
	delta_ext(0.0,xb);
}

void RoadPart::output_func(Bag<IO_Type>& yb)
{
	if (vehicle != NULL)
	{
		if (arived) return;
		if (can_go) // vozidlo muze odjet
		{
			IO_Type y(out_depart, (io_type*)vehicle); // posleme dal
			yb.insert(y);

			IO_Type q(out_free, new io_type()); // a posleme pro dalsi
			yb.insert(q);
		}
	}
}

double RoadPart::ta()
{
	if (vehicle != NULL)
	{
		if (arived) return delay; // move time
		if (can_go) return 0;
	}
	return DBL_MAX;
}

void RoadPart::gc_output(Bag<IO_Type>& g)
{
	// Delete the outgoing customer objects
	Bag<IO_Type>::iterator i;
	for (i = g.begin(); i != g.end(); i++)
	{
		delete (*i).value;
	}
}

RoadPart::~RoadPart()
{
	delete vehicle;
}
